class CommitmentService {

    boolean transactional = true

    /**
     * Oblicza saldo po danej operacji
     * Używać tylko przy dodawaniu nowej operacji,
     * po edycji operacji na koncie używać recomputeBalance(User person)
     */
    def computeBalance(Commitment commitment) {

        User person = commitment.user
        SortedSet commitments = person.commitments

        if (commitments.size() > 0) {
            Commitment lastCommitment = commitments.first()

            commitment.balance = lastCommitment.balance + commitment.value
        }
        else {
            commitment.balance = commitment.value
        }
    }

    /**
     * Oblicza bieżące saldo konta danego user'a
     */
    def getBalanceForUser(User person) {

        SortedSet commitments = person.commitments

        if (commitments.size() > 0) {
            Commitment lastCommitment = commitments.first()

            return lastCommitment.balance
        }
        else return 0
    }

    /**
     * Przelicza salda wszystkich operacji na koncie danego user'a
     * po usunięciu lub edycji jakiejś operacji
     */
    def recomputeBalance(User person) {
        Commitment[] commitments = person.commitments.toArray(
            new Commitment[person.commitments.size()])

        int newBalance = 0

        for (int i = commitments.length - 1; i >= 0; i--) {
            newBalance += commitments[i].value
            commitments[i].balance = newBalance
        }
    }

    /**
     * Tworzy operację na koncie potrącą z niego liczbę brykietów należną za
     * wygraną aukcję
     */
    def createCommitmentForAuction(Offer offer) {
        User person = offer.person
        Auction auction = offer.auction

        CommitmentType ct = CommitmentType.findByName("Aukcja")

        if (!ct) {
            ct = new CommitmentType(
                name: "Aukcja",
                description: "Brykiety pobrane za wygraną aukcję"
            ).save()
        }

        String commitmentDescription =
            "Aukcja nr " + auction.id + ": " + auction.title

        Commitment commitment = new Commitment(
            user: person,
            commitmentType: ct,
            value: -offer.price,
            description: commitmentDescription
        )

        computeBalance(commitment)//obliczamy saldo po operacji

        if (commitment.save()) {
            person.addToCommitments(commitment)
            ct.addToCommitments(commitment)
        }
        else {
            //TODO logowanie błędu
        }
    }

}
